<template>
    <div class="form-designer">
        <!-- 顶部头部信息栏 -->
        <div class="header-bar">
            <div class="header-left">
                <img src="@/assets/logo.png" alt="logo" class="logo" />
                <span class="company-name">WorkFox 表单设计器</span>
            </div>
            <div class="header-right">
                <el-button :icon="Monitor" type="primary" plain @click="openPreviewDialog">预览</el-button>
                <el-button :icon="Select" type="success" plain @click="handleSave"
                    v-if="config.showSaveButton">保存</el-button>
                <el-button :icon="CloseBold" type="primary" link @click="emit('close')"
                    v-if="config.showCloseButton">关闭</el-button>
                <el-button :icon="Delete" type="primary" link @click="resetFormJson(true)">清空组件</el-button>
                <el-button :icon="Edit" type="primary" link @click="changeWin">{{ showJSONData ? '组件视图' :
                    'JSON视图' }}</el-button>
                <slot name="heardButtons"></slot><!-- 按钮插槽 -->
            </div>
        </div>

        <div class="main-content">
            <!-- 左侧组件面板 -->
            <div class="left-panel">
                <WidgetGroup />
            </div>
            <!-- 中间表单画布 -->
            <div class="center-canvas">
                <el-form id="formDesigner" v-if="!showJSONData" v-bind="formConfig" :model="formData" label-width="auto"
                    style="width: 100%;" @click.stop="selectWidgetId = null">
                    <draggable v-model="widgetList" group="form" item-key="id" class="form-canvas" :animation="150"
                        @add="onAdd">
                        <template #item="{ element, index }">
                            <component :is="designer.renderComponent(element)" :config="element" :index="index" />
                        </template>
                    </draggable>
                </el-form>
                <div v-else>
                    <div class="json-buttons">
                        <el-button :icon="Refresh" link type="primary" @click.stop="saveJSONData">同步JSON数据</el-button>
                        <el-button :icon="Refresh" link type="primary" @click.stop="handleFormat">JSON格式化</el-button>
                    </div>
                    <CodeEditor v-model="JSONData" class="json-edit" />
                </div>
            </div>
            <!-- 右侧配置面板 -->
            <div class="right-panel">
                <ConfigGroup />
            </div>
        </div>

        <!-- 预览弹窗 -->
        <FormPreviewDialog ref="previewDialogRef" :json-config="formJson" />
    </div>
</template>

<script setup>
import { ref, provide, watch, onMounted, nextTick } from 'vue';
import designer from '@/utils/designer'
import WidgetGroup from './widget-gropu/WidgetGroup.vue';
import ConfigGroup from './config-group/ConfigGroup.vue';
import CodeEditor from './config-group/CodeEditor.vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { Select, CloseBold, Refresh, Edit, Monitor, Delete } from '@element-plus/icons-vue';
import { formatCode } from '@/utils/formatCode'
import FormPreviewDialog from '@/components/render/FormPreviewDialog.vue'
import { executeEventHandler } from '@/utils/eventExecutor'

const emit = defineEmits(['save', 'close'])

// 表单数据
const formData = ref({})

// 当前选中组件
const selectWidgetId = ref()

// 画布中的表单组件
const widgetList = ref([]);

// 表单全局配置
const formConfig = ref({
    labelWidth: 'auto',//标签宽度
    labelPosition: 'right',
    size: 'default',//组件尺寸
    disabled: false,//是否禁用
    scrollToError: true,//滚动到检验错误位置
    showMessage: true,//是否显示检验错误信息
    events: {
        onMounted: ''
    },
    globalStyle: ''
})

// 提供给所有下层组件
provide('designer', designer)
provide('formData', formData)
provide('selectWidgetId', selectWidgetId)
provide('widgetList', widgetList)
provide('formConfig', formConfig)

// 定义 props
const props = defineProps({
    config: {
        type: Object,
        default: () => ({
            showSaveButton: true,// 显示保存按钮
            showCloseButton: true,// 显示关闭按钮
            loadLocalData: true// 设计器挂载时加载本地数据
        })
    },
    formJson: {
        type: Object,
        default: () => ({}),
    },
    data: {
        type: Object,
        default: () => ({})
    },
    fieldData: {// 后端字段
        type: Object,
        default: () => ({
            fields: [],// 主表字段
            children: []// 子表字段
        })
    },
    requestHeaders: {
        type: Object,
        default: () => ({})
    },
    uploadApi: {
        type: String,
        default: ''
    },
    customWidgetList: {
        type: Array,
        default: () => ([])
    }
});

const requestHeadersRef = ref(props.requestHeaders)
const fieldDataRef = ref(props.fieldData)
const customWidgetListRef = ref(props.customWidgetList)

// 监听字段列表的变化
watch(() => props.fieldData, (data) => {
    if (data) {
        fieldDataRef.value = data
    }
}, { deep: true, immediate: true })

// 监听自定义组件列表的变化
watch(() => props.customWidgetList, (data) => {
    if (data) {
        customWidgetListRef.value = data
    }
}, { deep: true, immediate: true })


// 监听请求头的变化
watch(() => props.requestHeaders, (headers) => {
    if (headers) {
        requestHeadersRef.value = headers
        localStorage.setItem('requestHeaders', JSON.stringify(headers))
    }
}, { deep: true, immediate: true })

provide('requestHeaders', requestHeadersRef)
provide('fieldData', fieldDataRef)
provide('customWidgetList', customWidgetListRef)
provide('uploadApi', props.uploadApi)

// 当组件被添加到画布时触发
const onAdd = (evt) => {
    selectWidgetId.value = widgetList.value[evt.newIndex].id
};

const showJSONData = ref(false)
const JSONData = ref('')

const handleFormat = async () => {
    JSONData.value = await formatCode(JSONData.value, 'json')
}

const saveJSONData = () => {
    try {
        let data = JSON.parse(JSONData.value)
        completeWidgetList(data.widgetList)
        widgetList.value = data.widgetList
        formConfig.value = data.formConfig
        changeWin()
    } catch (err) {
        ElMessage.error('JSON数据格式错误解析失败！' + err)
    }
}
const changeWin = () => {
    showJSONData.value = !showJSONData.value
    if (showJSONData) {
        JSONData.value = JSON.stringify({
            formConfig: formConfig.value,
            widgetList: widgetList.value
        })
        handleFormat()
    }
}

const completeWidgetList = (widgetList) => {
  if (!Array.isArray(widgetList)) return;
  widgetList.forEach(widget => {
    let defaultWidget = designer.getWidgetJsonByType(widget.type);
    if( !defaultWidget ) {// 补充自定义组件
        defaultWidget = customWidgetListRef.value.find(item => item.type === widget.type)
    }
    if (defaultWidget) {
      // 补充 widget 第一层缺失字段
      for (const key in defaultWidget) {
        if (!(key in widget) || widget[key] === null) {
          widget[key] = deepClone(defaultWidget[key]);
        } else if (key === 'attributes') {
          const defaultAttrs = defaultWidget.attributes || {};
          if (widget.attributes === null || typeof widget.attributes !== 'object') {
            widget.attributes = deepClone(defaultAttrs);
          } else {
            const actualAttrs = widget.attributes;
            for (const attrKey in defaultAttrs) {
              if (!(attrKey in actualAttrs) || actualAttrs[attrKey] === null) {
                actualAttrs[attrKey] = deepClone(defaultAttrs[attrKey]);
              }
            }
          }
        }
      }
    }
    // 确保 children 至少是个空数组
    if (!Array.isArray(widget.children)) {
      widget.children = [];
    }
    // 递归处理子组件
    completeWidgetList(widget.children);
  });
};

// 简单深拷贝（确保不引用原始默认对象）
const deepClone = (obj) => {
    return JSON.parse(JSON.stringify(obj));
}

// 预览弹窗
const previewDialogRef = ref()
const openPreviewDialog = () => {
    const previewJson = { formConfig: formConfig.value, widgetList: widgetList.value }
    previewDialogRef.value.open(previewJson)
}

// 同步表单内容
watch(() => props.formJson, (config) => {
    if (config && config.widgetList) {
        widgetList.value = config.widgetList
    }
    if (config && config.formConfig) {
        formConfig.value = config.formConfig
    }
}, { deep: true, immediate: true })

// 清空设计器内容
const resetFormJson = async (showMessage = false) => {
    if (showMessage) {
        try {
            await ElMessageBox.confirm(
                '确定要清空表单设计内容吗？此操作不可恢复！',
                '提示',
                {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                }
            )
            localStorage.removeItem('formJson');
            formData.value = {}
            widgetList.value = []
        } catch (err) {
            // 点击了取消，不清空
        }
    } else {
        formData.value = {}
        widgetList.value = []
    }
}

const handleSave = async () => {
    const data = await getFormJson()
    if (props.config.loadLocalData) {
        localStorage.setItem('formJson', JSON.stringify(data))
    }
    emit('save', data)
}

const getFormJson = async () => {
    return {
        formConfig: formConfig.value,
        widgetList: widgetList.value
    }
}

const setFormJson = (json) => {
    formData.value = {}
    formConfig.value = json.formConfig || {
        labelWidth: 'auto',//标签宽度
        labelPosition: 'right',
        size: 'default',//组件尺寸
        disabled: false,//是否禁用
        scrollToError: true,//滚动到检验错误位置
        showMessage: true,//是否显示检验错误信息
        events: {
            onMounted: ''
        }
    };
    json.widgetList = json.widgetList || []
    completeWidgetList(json.widgetList)
    widgetList.value = json.widgetList;
}

onMounted(async () => {
    await nextTick()
    if (props.config.loadLocalData && widgetList.value.length == 0) {
        let data = localStorage.getItem('formJson')
        if (data) {
            setFormJson(JSON.parse(data))
        }
    }
    executeEventHandler(formConfig.value.events?.onMounted,
        { formConfig: formConfig.value, formData: formData.value, widgetList: widgetList.value }
    )
})

// 应用表单全局样式，只维护一个 style 标签
const applyGlobalStyle = (styleContent) => {
    let styleEl = document.getElementById('form-global-style')
    if (!styleEl) {
        styleEl = document.createElement('style')
        styleEl.id = 'form-global-style'
        styleEl.type = 'text/css'
        document.head.appendChild(styleEl)
    }
    // 更新 style 内容
    styleEl.textContent = styleContent || ''
}

watch(
    () => formConfig.value.globalStyle,
    (newVal) => {
        applyGlobalStyle(newVal)
    },
    { immediate: true } // 立即执行一次
)

defineExpose({
    getFormJson,
    resetFormJson,
    setFormJson
})
</script>

<style scoped>
.form-designer {
    display: flex;
    flex-direction: column;
    height: 100vh;
    width: 100%;
}

.header-bar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    height: 56px;
    padding: 0 20px;
    background-color: var(--el-bg-color);
    border-bottom: 1px solid var(--el-border-color);
    box-shadow: 0 2px 8px var(--el-color-shadow);
    z-index: 10;
}

.header-left {
    display: flex;
    align-items: center;
}

.logo {
    width: 32px;
    height: 32px;
    margin-right: 10px;
}

.company-name {
    font-size: 16px;
    font-weight: 600;
    color: var(--el-text-color-primary);
}

.header-right>.el-button {
    margin-left: 10px;
}

.main-content {
    display: flex;
    flex: 1;
    height: calc(100% - 56px);
}

.left-panel {
    width: 250px;
    background-color: var(--el-bg-color-light);
    border-right: 1px solid var(--el-border-color);
    overflow-y: auto;
}

.center-canvas {
    flex: 1;
    padding: 5px;
    overflow-y: auto;
    background-color: var(--el-bg-color);
}

.form-canvas {
    display: flex;
    border: 2px dashed var(--el-border-color);
    flex-direction: column;
    padding: 8px;
    min-height: calc(100vh - 70px);
}

.json-buttons {
    display: flex;
    flex-direction: row;
    margin-bottom: 5px;
    gap: 5px;
}

.json-edit {
    height: calc(100vh - 100px);
}

.right-panel {
    width: 290px;
    background-color: var(--el-bg-color-light);
    border-left: 1px solid var(--el-border-color);
    overflow-y: auto;
}
</style>